const vscode = require('vscode');
const Utility = require( './Utility.js');
const { exec } = require('child_process');
const fs = require('fs');
const path = require('path');

const ExtCommands =
{
    OpenProj : OpenProj,
    
    ExecSvnCmd : ExecCmd,
    
    UpdateMsgFromSvn : UpdateMsgFromSvn,
    
    GenLuaFuncDoc : GenLuaFuncDoc,
    GenLuaTableDoc : GenLuaTableDoc,
    
    OpenBCompare : OpenBCompare,
};

const EPathType =
{
    All : 0,
    Lua : 1,
    Prefab : 2,
    ThisFile : 3,
}

/**
 * @param {number} type
 * @param {{ path: string; }} cfg
 */
function GetPath(type, cfg)
{
    let path = "";
    switch (type) 
    {
        case EPathType.All:
            path = cfg.path.replace("\\Client\\Assets\\Code_Lua", "")
            break;
        case EPathType.Lua:
            path = cfg.path;
            break;
        case EPathType.Prefab:
            path = cfg.path.replace("Code_Lua", "Resources\\UI\\Prefabs")
            break;
        case EPathType.ThisFile:
            path = vscode.window.activeTextEditor.document.fileName;
            break;
        default:
            break;
    }
    return path;
}

/**
 * @param {string | any[]} splits
 */
function AnalysisInput(splits)
{
    var res = {};
    if(splits.length == 0) { return res; } 
    res.first = splits[0];
    res.pathType = EPathType.Lua;
    for (let index = 0; index < splits.length; index++) 
    {
        switch (splits[index]) 
        {
            case "nw":
                res.newWindow = true;
                break;
            case "tw":
                res.newWindow = false;
                break;
            case "all":
                res.pathType = EPathType.All;
                break;
            case "pf":
                res.pathType = EPathType.Prefab;
                break;
            case "tf":
                res.pathType = EPathType.ThisFile;
                break;
            case "ud":
                res.svncmd = "update";
                break;
            case "cm":
                res.svncmd = "commit";
                break;
            case "log":
                res.svncmd = "log";
                break;
            case "cl":
                res.svncmd = "cleanup";
                break;
            case "rvt":
                res.svncmd = "revert";
                break;
            case "blm":
                res.svncmd = "blame";
                res.pathType = EPathType.ThisFile;
                break;
            case "cmp":
                res.compare = true;
            default:
                break;
        }
    }
    return res;
}

function OpenProj() {
    vscode.window.showInputBox({ prompt: '请输入项目名称' }).then((input) => 
    {
        if (input == undefined || input == "") { return; }
        let res = AnalysisInput(input.split(" "));
        let name = res.first;
        if (name == undefined || name == "") 
        {
            vscode.window.showErrorMessage("项目名称不能为空");
            return;
        }
        let cfg = Utility.GetProjPathCfg(name);
        if (cfg == undefined) 
        {
            vscode.window.showErrorMessage("项目路径未配置");
            return;
        }
        
        try
        {
            let workspaceUri = vscode.Uri.file(cfg.path);
            let openInNewWindow = false;
            if (res.newWindow != undefined) { openInNewWindow = res.newWindow; }
            else { openInNewWindow = cfg.newWindow; }
            vscode.commands.executeCommand('vscode.openFolder', workspaceUri, openInNewWindow);
            if(name === "msg")
            {
                UpdateMsgFromSvn()
            }
        }
        catch (error) 
        {
            vscode.window.showErrorMessage("打开工作区失败");
        }
    });
}

function UpdateMsgFromSvn() {

    const workspaceFolder = Utility.msgWorkspacePath;
    
    let urlList = {};
    // let localDirList = {}
    let projPathCfg = Utility.projPathCfg;
    for (const key in projPathCfg) {
        if (projPathCfg.hasOwnProperty(key)) {
            const element = projPathCfg[key];
            if(element.svnurl == undefined || element.svnurl == ""){
                continue;                
            }
            urlList[key] = element.svnurl;
            // localDirList[key] = path.join(workspaceFolder, key);
        }
    }
    
    // 替换urlList中的路径到xy.h
    for (const key in urlList) {
        if (urlList.hasOwnProperty(key)) {
            const url = urlList[key];
            urlList[key] = url + "/tools/NetProtor/msg/xy.h";
        }
    }
    
    
    // 对于每个项目的xy.h从仓库下载
    for (const key in urlList) {
        if (urlList.hasOwnProperty(key)) {
            const url = urlList[key];
            // const localDir = localDirList[key];
            const renamedFile = path.join(workspaceFolder, key + "_xy.h").replace(/\\/g, '/');

            // // 如果文件夹不存在，则创建
            // if (!fs.existsSync(localDir)) {
            //     fs.mkdirSync(localDir   , { recursive: true });
            // }
            
            // 如果文件存在，则删除
            if (fs.existsSync(renamedFile)) {
                fs.unlinkSync(renamedFile);
            }
            
            // 从仓库下载
            exec(`svn export ${url} ${renamedFile}`, (error, stdout, stderr) => {
                if (error) 
                {
                    vscode.window.showErrorMessage(`error: ${error}`);
                    return;
                }
                if (stderr)
                {
                    vscode.window.showErrorMessage(`stderr: ${stderr}`);
                    return;
                }
                // vscode.window.showInformationMessage(`Complete: exec svn export ${url} ${renamedFile}`);
            });
            
        }
    }
}


function ExecCmd()
{
    vscode.window.showInputBox({ prompt: '请输入指令 ud->update | cm->commit | log->log' }).then((input) => 
    {
        if (input == undefined || input == "") { return; }
        let splits = input.split(" ");
        let res = AnalysisInput(splits);
        let name = splits[1];
        if (name == undefined || name == "") 
        {
            vscode.window.showErrorMessage("项目名称不能为空");
            return;
        }
        let cfg = Utility.GetProjPathCfg(name);
        if (cfg == undefined && res.pathType != EPathType.ThisFile) 
        {
            vscode.window.showErrorMessage("项目路径未配置");
            return;
        }
        
        if(res.svncmd != undefined)
        {
            ExecSvnCmd(res, cfg);
            return;
        }
        
        if(res.compare != undefined)
        {
            let leftName = splits[1];
            let rightName = splits[2];
            OpenBCompare(leftName, rightName, res);
            return;
        }
        
        // 未知指令
        vscode.window.showErrorMessage("未知指令");
    });
}

function ExecSvnCmd(res, cfg) {
    let path = GetPath(res.pathType, cfg);
        
    let svncmd = res.svncmd;
    try
    {
        vscode.window.showInformationMessage(`exec svn cmd ${svncmd} ${path}`);
        exec(`"${Utility.tortoiseSVN}" /command:${svncmd} /path:"${path}"`, (error, stdout, stderr) => {
            if (error) 
            {
                vscode.window.showErrorMessage(`error: ${error}`);
                return;
            }
            if (stderr)
            {
                vscode.window.showErrorMessage(`stderr: ${stderr}`);
                return;
            }
            vscode.window.showInformationMessage(`Complete: exec svn ${svncmd} ${path}`);
        });
    }
    catch (error) 
    {
        vscode.window.showErrorMessage(`Fail: exec svn ${svncmd} ${path}`);
    }
}

function OpenBCompare(leftName, rightName, res) {
    let bcomparePath = Utility.bComparePath;
    if (bcomparePath == undefined || bcomparePath == "") {
        vscode.window.showErrorMessage("请配置Beyond Compare路径");
        return;
    }
    
    if (leftName == undefined || leftName == "") 
    {
        vscode.window.showErrorMessage("项目名称不能为空");
        return;
    }
    if (rightName == undefined || rightName == "")
    {
        vscode.window.showErrorMessage("项目名称不能为空");
        return;
    }
    let leftCfg = Utility.GetProjPathCfg(leftName);
    if (leftCfg == undefined && res.pathType != EPathType.ThisFile) 
    {
        vscode.window.showErrorMessage("项目路径未配置");
        return;
    }
    let rightCfg = Utility.GetProjPathCfg(rightName);
    if (rightCfg == undefined && res.pathType != EPathType.ThisFile) 
    {
        vscode.window.showErrorMessage("项目路径未配置");
        return;
    }
    
    let leftPath = GetPath(res.pathType, leftCfg);
    let rightPath = GetPath(res.pathType, rightCfg);
    
    try
    {
        vscode.window.showInformationMessage(`exec bcompare ${leftPath} ${rightPath}`);
        exec(`"${bcomparePath}" "${leftPath}" "${rightPath}"`, (error, stdout, stderr) => {
            if (error) 
            {
                vscode.window.showErrorMessage(`error: ${error}`);
                return;
            }
            if (stderr)
            {
                vscode.window.showErrorMessage(`stderr: ${stderr}`);
                return;
            }
            vscode.window.showInformationMessage(`Complete: exec bcompare ${leftPath} ${rightPath}`);
        });
    }
    catch (error) 
    {
        vscode.window.showErrorMessage(`Fail: exec bcompare ${leftPath} ${rightPath}`);
    }
}

function GenLuaFuncDoc()
{
    let editor = vscode.window.activeTextEditor;
    if (editor) {
        let document = editor.document;
        let position = editor.selection.active;  // 获取光标的位置
        // 从光标的位置开始，向后查找函数定义
        let text = document.lineAt(position.line).text;

        // 使用正则表达式匹配函数定义
        let match = text.match(/function.*\((.*)\)/);
        if (match) {
            // 提取参数
            let params = match[1].split(',').map(param => param.trim());

            // 生成文档注释
            let doc = `--- 在此添加描述\n`;
            params.forEach(param => {
                if (param != "") {
                    if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(param)) {
                        return;
                    }
                    doc += `--- @param ${param} any 变量描述\n`;
                }
            });
            doc += '--- @return';

            // 在函数开始处插入文档注释
            editor.edit(editBuilder => {
                editBuilder.insert(new vscode.Position(position.line, 0), doc + '\n');
            });
        }
        else {
            vscode.window.showInformationMessage("这似乎不是一个函数定义");
        }
    }
}

function GenLuaTableDoc() {
    let editor = vscode.window.activeTextEditor;
    if (editor) {
        let document = editor.document;
        let position = editor.selection.active;  // 获取光标的位置

        // 只检查当前行
        let line = position.line;
        let text = document.lineAt(line).text;

        // 使用正则表达式匹配表定义
        let match = text.match(/\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*(\{)?/);
        if (match) {
            // 提取表名
            let tableName = match[1];

            // 检查当前行的下一行是否是表的开始
            let nextLineText = "";
            if (line + 1 < document.lineCount) {
                nextLineText = document.lineAt(line + 1).text.trim();
            }

            // 检查当前行是否是表的开始
            let isTableStart = match[2] != undefined || nextLineText.startsWith("{");

            if (isTableStart) {
                // 生成文档注释
                let doc = `---@class ${tableName} : table\n`;

                // 向后查找字段定义
                for (let fieldLine = line + 2; fieldLine < document.lineCount; fieldLine++) {
                    let fieldText = document.lineAt(fieldLine).text;

                    // 使用正则表达式匹配字段定义
                    let fieldMatch = fieldText.match(/([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*(.*),/);
                    if (fieldMatch) {
                        // 提取字段名
                        let fieldName = fieldMatch[1];

                        // 生成字段的文档注释
                        doc += `---@field ${fieldName} any 字段描述\n`;
                    } else if (fieldText.trim() === "}") {
                        // 如果遇到表定义的结束，就停止查找
                        break;
                    }
                }

                // 在表开始处插入文档注释
                editor.edit(editBuilder => {
                    editBuilder.insert(new vscode.Position(line, 0), doc);
                });
            } else {
                vscode.window.showInformationMessage("这似乎不是一个表定义");
            }
        } else {
            vscode.window.showInformationMessage("这似乎不是一个表定义");
        }
    }
}


module.exports = ExtCommands;